package com.zeus.core.open.api;

import com.zeus.common.enums.ZeusAlarmLevelEnum;
import com.zeus.common.log.ZeusLoggerConfig;
import com.zeus.core.report.ZeusReportApiClient;
import com.zeus.core.report.ZeusReportClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Arrays;
import java.util.List;

/**
 * 宙斯报警
 *
 * @author wangfeixiong126@gmail.com  2021/6/21 23:40
 */
public class ZeusAlarm {
    private final static Logger logger = LoggerFactory.getLogger(ZeusAlarm.class);

    /**
     * 宙斯方法名列表
     */
    private static final List<String> ZEUS_METHOD_NAME_LIST = Arrays.asList("p0", "p1", "p2", "p3", "p4");

    /**
     * P0级别报警, 必须提供解决办法
     * 
     * @param message   告警信息
     * @param solution  解决办法
     * @author wangfeixiong126@gmail.com  2021/6/21 23:46
     */
    public static void p0(String message, String solution) {
        alarm(ZeusAlarmLevelEnum.P0, message, solution);
    }

    /**
     * p1级别报警, 必须提供解决办法
     *
     * @param message   告警信息
     * @param solution  解决办法
     * @author wangfeixiong126@gmail.com  2021/6/21 23:46
     */
    public static void p1(String message, String solution) {
        alarm(ZeusAlarmLevelEnum.P1, message, solution);
    }

    /**
     * p2级别报警
     *
     * @param message   告警信息
     * @author wangfeixiong126@gmail.com  2021/6/21 23:46
     */
    public static void p2(String message) {
        alarm(ZeusAlarmLevelEnum.P2, message, null);
    }

    /**
     * p2级别报警
     *
     * @param message   告警信息
     * @param solution  解决办法
     * @author wangfeixiong126@gmail.com  2021/6/21 23:46
     */
    public static void p2(String message, String solution) {
        alarm(ZeusAlarmLevelEnum.P2, message, solution);
    }

    /**
     * p3级别报警
     *
     * @param message   告警信息
     * @author wangfeixiong126@gmail.com  2021/6/21 23:46
     */
    public static void p3(String message) {
        alarm(ZeusAlarmLevelEnum.P3, message, null);
    }

    /**
     * p3级别报警
     *
     * @param message   告警信息
     * @param solution  解决办法
     * @author wangfeixiong126@gmail.com  2021/6/21 23:46
     */
    public static void p3(String message, String solution) {
        alarm(ZeusAlarmLevelEnum.P3, message, solution);
    }

    /**
     * p4级别报警
     *
     * @param message   告警信息
     * @author wangfeixiong126@gmail.com  2021/6/21 23:46
     */
    public static void p4(String message) {
        alarm(ZeusAlarmLevelEnum.P4, message, null);
    }

    /**
     * p4级别报警
     *
     * @param message   告警信息
     * @param solution  解决办法
     * @author wangfeixiong126@gmail.com  2021/6/21 23:46
     */
    public static void p4(String message, String solution) {
        alarm(ZeusAlarmLevelEnum.P4, message, solution);
    }

    /**
     * 报警
     *
     * @param message   告警信息
     * @param solution  解决办法
     * @author wangfeixiong126@gmail.com  2021/6/21 23:48
     */
    private static void alarm(ZeusAlarmLevelEnum levelEnum, String message, String solution) {
        try {
            // 获取调用者信息
            String className = null;
            String methodName = null;
            String fileName = null;
            Integer lineNumber = null;
            StackTraceElement invokeClassInfo = getInvokeClassInfo();
            if (invokeClassInfo != null) {
                className = invokeClassInfo.getClassName();
                methodName = invokeClassInfo.getMethodName();
                fileName = invokeClassInfo.getFileName();
                lineNumber = invokeClassInfo.getLineNumber();
            }

            ZeusReportClient client =
                new ZeusReportApiClient(levelEnum, message, solution, className, methodName, lineNumber, fileName);
            client.complete();
        } catch (Throwable e) {
            if (logger.isWarnEnabled() && ZeusLoggerConfig.needEnableLogger()) {
                logger.warn("### Zeus监控服务, 报警执行失败 >> errMsg = {}", e.getMessage());
            }
        }
    }

    /**
     * 获取调用类信息
     * 
     * @return StackTraceElement
     * @author wangfeixiong126@gmail.com  2021/8/12 11:22
     */
    private static StackTraceElement getInvokeClassInfo() {
        try {
            StackTraceElement[] stackTrace = new Throwable().getStackTrace();
            int index = -1;
            for (int i = 0; i < stackTrace.length; i++) {
                StackTraceElement element = stackTrace[i];
                if (element != null && ZEUS_METHOD_NAME_LIST.contains(element.getMethodName())) {
                    index = i + 1;
                    break;
                }
            }
            if (index > 0 && index < stackTrace.length - 1) {
                return stackTrace[index];
            }
        } catch (Throwable ignored) {
            // 忽略
        }
        return null;
    }
}
